home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
graphics
/
font3d10.zip
/
build.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-15
|
18KB
|
552 lines
//=================================================================================================
// Build.CPP
//-------------------------------------------------------------------------------------------------
//
// Copyright (c) 1994 by Todd A. Prater
// All rights reserved.
//
//=================================================================================================
#include <stdlib.h>
#include <fstream.h>
#include "Config.H"
#include "Vector.H"
#include "TrueType.H"
#include "Geometry.H"
#include "Build.H"
#define IGNORE 2
#define INSIDE 1
#define OUTSIDE 0
// ******************************************************
// NOTE: Please excuse the debugging code
// ******************************************************
//===========================================================================================================
// PolygonizeContour
//-----------------------------------------------------------------------------------------------------------
//===========================================================================================================
void PolygonizeContour(TTFont& font,
USHORT glyphnum,
USHORT contournum,
USHORT resolution,
DOUBLE depth,
POLYGON& polygon )
{
ULONG i,j;
ULONG polyi;
ULONG offcount,pointcount;
ULONG consecutiveoffcount;
INT lastwasoff;
INT cur_type,prev_type,next_type;
VECTOR cp1,cp2,cp3,cur_point,prev_point,next_point;
DOUBLE cur_x,cur_y,prev_x,prev_y,next_x,next_y;
DOUBLE tstep;
if (font.NumContours(glyphnum)<1)
return;
if (contournum>=font.NumContours(glyphnum))
return;
if(polygon.numpoints>0)
{
delete polygon.pointlist;
polygon.numpoints=0;
}
lastwasoff=0;
consecutiveoffcount=0;
offcount=0;
for(i=0;i<font.NumPoints(glyphnum,contournum);i++)
{
// if (font.FontPointType(glyphnum,contournum,i)==ON_CURVE) cout<<i<<": ON"<<endl;
// else cout<<i<<": OFF"<<endl;
if(font.FontPointType(glyphnum,contournum,i)==OFF_CURVE)
{
offcount++;
if(lastwasoff)
consecutiveoffcount++;
lastwasoff=1;
}
else
lastwasoff=0;
}
polygon.numpoints = font.NumPoints(glyphnum,contournum) + offcount*(resolution-2) + consecutiveoffcount;
polygon.pointlist = new VECTOR[polygon.numpoints+40]; // Temporary fix (give some playing room...)
polyi=0;
// pointcount = font.NumPoints(glyphnum,contournum);
for(i=0;i<font.NumPoints(glyphnum,contournum);i++)
{
if (font.FontPointType(glyphnum,contournum,i)==ON_CURVE)
{
//cout<<"OnCURVE: "<<i<<endl;
polygon.pointlist[polyi] = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(),
(DOUBLE)font.FontPointY(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(), depth);
polyi++;
}
else
{
//cout<<"OffCURVE: "<<i<<endl;
if(font.FontPointType(glyphnum,contournum,i-1)==ON_CURVE)
{
cp1 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i-1)/(DOUBLE)font.UnitsPerEm(),
(DOUBLE)font.FontPointY(glyphnum,contournum,i-1)/(DOUBLE)font.UnitsPerEm(), depth);
}
else
{
cp1 = VECTOR(((DOUBLE)font.FontPointX(glyphnum,contournum,i-1)+(DOUBLE)font.FontPointX(glyphnum,contournum,i))/2/(DOUBLE)font.UnitsPerEm(),
((DOUBLE)font.FontPointY(glyphnum,contournum,i-1)+(DOUBLE)font.FontPointY(glyphnum,contournum,i))/2/(DOUBLE)font.UnitsPerEm(), depth);
}
cp2 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(),
(DOUBLE)font.FontPointY(glyphnum,contournum,i)/(DOUBLE)font.UnitsPerEm(), depth);
if (i==(font.NumPoints(glyphnum,contournum)-1))
{
//cout<<"THE LAST ONE"<<endl;
cp3 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,0)/(DOUBLE)font.UnitsPerEm(),
(DOUBLE)font.FontPointY(glyphnum,contournum,0)/(DOUBLE)font.UnitsPerEm(), depth);
}
else
{
if(font.FontPointType(glyphnum,contournum,i+1)==ON_CURVE)
{
cp3 = VECTOR((DOUBLE)font.FontPointX(glyphnum,contournum,i+1)/(DOUBLE)font.UnitsPerEm(),
(DOUBLE)font.FontPointY(glyphnum,contournum,i+1)/(DOUBLE)font.UnitsPerEm(), depth);
i++;
}
else
{
cp3 = VECTOR(((DOUBLE)font.FontPointX(glyphnum,contournum,i)+(DOUBLE)font.FontPointX(glyphnum,contournum,i+1))/2/(DOUBLE)font.UnitsPerEm(),
((DOUBLE)font.FontPointY(glyphnum,contournum,i)+(DOUBLE)font.FontPointY(glyphnum,contournum,i+1))/2/(DOUBLE)font.UnitsPerEm(), depth);
}
}
tstep = 1.0/(DOUBLE)resolution;
for(j=0;j<resolution;j++)
{
polygon.pointlist[polyi] = ApproximateQuadraticSpline(cp1,cp2,cp3,tstep*(j+1));
polyi++;
}
}
}
if ( (polygon.pointlist[polyi-1].x==polygon.pointlist[0].x)
&& (polygon.pointlist[polyi-1].y==polygon.pointlist[0].y))
{
//cout<<"LAST IS FIRST"<<endl;
polyi--; //temporary fix....
}
polygon.numpoints = polyi;
polygon.orientation = polygon.findOrientation();
//cout<<polygon<<"P";
}
//===========================================================================================================
// TriangulateFace
//-----------------------------------------------------------------------------------------------------------
//===========================================================================================================
void TriangulateFace (TTFont& font,
USHORT glyphnum,
USHORT resolution,
DOUBLE shrinkFactor,
LIST<TRIANGLE>& triangleList)
{
int i,j,k;
BOOLEAN isAPair;
SHORT contourCount;
POLYGON* polyarray;
POLYGON* shrunkpolyarray;
BYTEPTR* relationship;
// cout<<"Beginning to triangulate..."<<endl;
contourCount = font.NumContours(glyphnum);
if (contourCount<1) return;
polyarray = new POLYGON[contourCount];
if (polyarray==NULL)
{
cout<<"ERROR: Out of memory."<<endl;
exit(1);
}
shrunkpolyarray=new POLYGON[contourCount];
if (shrunkpolyarray==NULL)
{
cout<<"ERROR: Out of memory."<<endl;
exit(1);
}
relationship = new BYTEPTR[contourCount];
if (relationship==NULL)
{
cout<<"ERROR: Out of memory."<<endl;
exit(1);
}
for (i=0;i<contourCount;i++)
{
relationship[i] = new BYTE[contourCount];
if (relationship[i]==NULL)
{
cout<<"ERROR: Out of memory."<<endl;
exit(1);
}
}
for (i=0;i<contourCount;i++)
{
PolygonizeContour(font,glyphnum,i,resolution,0.0,polyarray[i]);
if (shrinkFactor>0.0)
polyarray[i].Shrink(shrunkpolyarray[i],shrinkFactor);
}
//cout<<"All Contours Polygonized."<<endl;
for (i=0;i<contourCount;i++)
for (j=0;j<contourCount;j++)
if (i==j)
relationship[i][j]=IGNORE;
else if (polyarray[j].isInside(polyarray[i]))
relationship[i][j]=INSIDE;
else
relationship[i][j]=OUTSIDE;
for (i=0;i<contourCount;i++)
{
if (polyarray[i].orientation==CLOCKWISE)
{
for (j=0;j<contourCount;j++)
{
isAPair=FALSE;
if (relationship[i][j]==INSIDE && polyarray[j].orientation==COUNTER_CLOCKWISE)
{
isAPair=TRUE;
for (k=0;k<contourCount;k++)
{
if (k==j || k==i || relationship[k][j]==IGNORE) continue;
if (relationship[k][j]==INSIDE)
{
if (relationship[i][k]==INSIDE)
{
isAPair=FALSE;
exit;
}
}
else
continue;
}
}
if (isAPair)
{
if (shrinkFactor>0.0)
shrunkpolyarray[i].Combine(shrunkpolyarray[j]);
else
polyarray[i].Combine(polyarray[j]);
relationship[i][j]=IGNORE;
}
}
}
}
for (i=0;i<contourCount;i++)
{
if (polyarray[i].orientation==CLOCKWISE)
{
if (shrinkFactor>0.0)
shrunkpolyarray[i].Triangulate(triangleList);
else
polyarray[i].Triangulate(triangleList);
}
}
for (i=0;i<contourCount;i++)
{
delete polyarray[i].pointlist;
delete shrunkpolyarray[i].pointlist;
delete relationship[i];
}
delete polyarray;
delete shrunkpolyarray;
delete relationship;
}
//===========================================================================================================
// TriangulateEdges
//-----------------------------------------------------------------------------------------------------------
//===========================================================================================================
void TriangulateEdges(TTFont& font,
USHORT glyphnum,
USHORT resolution,
DOUBLE frontDepth,
DOUBLE backDepth,
DOUBLE angleThreshold,
LIST<TRIANGLE>& tlist)
{
INT i,j,k;
TRIANGLE* t1;
TRIANGLE* t2;
VECTOR previous,current1,current2,next;
VECTOR previousFacet,currentFacet,nextFacet;
VECTOR previousFacetNormal,currentFacetNormal,nextFacetNormal;
VECTOR averageNormal1,averageNormal2;
VECTOR p1,p2,p3,p4;
ULONG numberOfPoints;
SHORT contourCount;
POLYGON* polyarray;
VECTOR zDir(0,0,1);
DOUBLE angle1,angle2;
contourCount = font.NumContours(glyphnum);
if (contourCount<1) return;
polyarray = new POLYGON[contourCount];
if (polyarray==NULL)
{
cout<<"ERROR: Out of memory."<<endl;
exit(1);
}
for (i=0;i<contourCount;i++)
PolygonizeContour(font,glyphnum,i,resolution,0.0,polyarray[i]);
for (i=0;i<contourCount;i++)
{
numberOfPoints = polyarray[i].numpoints;
for (j=0;j<numberOfPoints;j++)
{
if (j==numberOfPoints-2)
{
previous = polyarray[i].pointlist[j-1];
current1 = polyarray[i].pointlist[j];
current2 = polyarray[i].pointlist[j+1];
next = polyarray[i].pointlist[0];
}
else if (j==numberOfPoints-1)
{
previous = polyarray[i].pointlist[j-1];
current1 = polyarray[i].pointlist[j];
current2 = polyarray[i].pointlist[0];
next = polyarray[i].pointlist[1];
}
else if (j==0)
{
previous = polyarray[i].pointlist[numberOfPoints-1];
current1 = polyarray[i].pointlist[j];
current2 = polyarray[i].pointlist[j+1];
next = polyarray[i].pointlist[j+2];
}
else
{
previous = polyarray[i].pointlist[j-1];
current1 = polyarray[i].pointlist[j];
current2 = polyarray[i].pointlist[j+1];
next = polyarray[i].pointlist[j+2];
}
previousFacet = ~(current1-previous);
currentFacet = ~(current2-current1);
nextFacet = ~(next-current2);
previousFacetNormal = zDir^previousFacet;
currentFacetNormal = zDir^currentFacet;
nextFacetNormal = zDir^nextFacet;
angle1 = acos(previousFacetNormal%currentFacetNormal);
angle2 = acos(currentFacetNormal%nextFacetNormal);
if (angle1<angleThreshold)
averageNormal1 = ~(previousFacetNormal+currentFacetNormal);
else
averageNormal1 = currentFacetNormal;
if (angle2<angleThreshold)
averageNormal2 = ~(currentFacetNormal+nextFacetNormal);
else
averageNormal2 = currentFacetNormal;
p1 = current1; p1.z=frontDepth;
p2 = current1; p2.z=backDepth;
p3 = current2; p3.z=frontDepth;
p4 = current2; p4.z=backDepth;
t1 = new TRIANGLE(p1,p2,p3,averageNormal1,averageNormal1,averageNormal2);
if (t1==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t2 = new TRIANGLE(p2,p3,p4,averageNormal1,averageNormal2,averageNormal2);
if (t2==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
tlist.Add(t1);
tlist.Add(t2);
}
}
delete polyarray;
}
// This routine doesn't quite work yet. Sometimes if the polygon is 'shrunk' too much,
// it can become self intersecting, which throws everything else off...
void TriangulateBevels(TTFont& font, INT code, INT resolution,
DOUBLE frontDepth, DOUBLE backDepth,
DOUBLE faceShrink, DOUBLE edgeShrink,
LIST<TRIANGLE>& tlist)
{
INT i,j;
TRIANGLE* t1;
TRIANGLE* t2;
TRIANGLE* t3;
TRIANGLE* t4;
INT glyphnum;
VECTOR p1,p2,p3,p4,p5,p6,p7,p8;
SHORT contourCount;
POLYGON* frontFacePolyArray;
POLYGON* frontEdgePolyArray;
POLYGON* backFacePolyArray;
POLYGON* backEdgePolyArray;
glyphnum = font.CharacterMap(code);
contourCount = font.NumContours(glyphnum);
if (contourCount<1) return;
frontFacePolyArray = new POLYGON[contourCount];
if (frontFacePolyArray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
frontEdgePolyArray = new POLYGON[contourCount];
if (frontEdgePolyArray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
backFacePolyArray = new POLYGON[contourCount];
if (backFacePolyArray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
backEdgePolyArray = new POLYGON[contourCount];
if (backEdgePolyArray==NULL) { cout<<"ERROR: Out of memory."<<endl; exit(1); }
for (i=0;i<contourCount;i++)
{
PolygonizeContour(font,glyphnum,i,resolution,frontDepth,frontEdgePolyArray[i]);
PolygonizeContour(font,glyphnum,i,resolution,backDepth,backEdgePolyArray[i]);
frontEdgePolyArray[i].Shrink(frontFacePolyArray[i],faceShrink);
backEdgePolyArray[i].Shrink(backFacePolyArray[i],faceShrink);
frontEdgePolyArray[i].SetDepth(frontDepth-edgeShrink);
backEdgePolyArray[i].SetDepth(backDepth+edgeShrink);
for (j=0;j<frontEdgePolyArray[i].numpoints-1;j++)
{
p1 = frontFacePolyArray[i].pointlist[j];
p2 = frontFacePolyArray[i].pointlist[j+1];
p3 = frontEdgePolyArray[i].pointlist[j];
p4 = frontEdgePolyArray[i].pointlist[j+1];
p5 = backEdgePolyArray[i].pointlist[j];
p6 = backEdgePolyArray[i].pointlist[j+1];
p7 = backFacePolyArray[i].pointlist[j];
p8 = backFacePolyArray[i].pointlist[j+1];
cout<<"VECTORS: "<<p1<<p2<<p3<<p4<<p5<<p6<<p7<<p8<<endl;
t1 = new TRIANGLE(p1,p3,p2);
if (t1==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t2 = new TRIANGLE(p2,p3,p4);
if (t2==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t3 = new TRIANGLE(p5,p7,p8);
if (t3==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t4 = new TRIANGLE(p5,p8,p6);
if (t4==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
tlist.Add(t1);
tlist.Add(t2);
tlist.Add(t3);
tlist.Add(t4);
}
p1 = frontFacePolyArray[i].pointlist[j];
p2 = frontFacePolyArray[i].pointlist[0];
p3 = frontEdgePolyArray[i].pointlist[j];
p4 = frontEdgePolyArray[i].pointlist[0];
p5 = backEdgePolyArray[i].pointlist[j];
p6 = backEdgePolyArray[i].pointlist[0];
p7 = backFacePolyArray[i].pointlist[j];
p8 = backFacePolyArray[i].pointlist[0];
t1 = new TRIANGLE(p1,p3,p2);
if (t1==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t2 = new TRIANGLE(p2,p3,p4);
if (t2==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t3 = new TRIANGLE(p5,p7,p8);
if (t3==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
t4 = new TRIANGLE(p5,p8,p6);
if (t4==NULL) { cout<<"ERROR: Out of memory"<<endl; exit(1); }
tlist.Add(t1);
tlist.Add(t2);
tlist.Add(t3);
tlist.Add(t4);
}
for (i=0;i<contourCount;i++)
{
delete frontFacePolyArray[i].pointlist;
delete frontEdgePolyArray[i].pointlist;
delete backEdgePolyArray[i].pointlist;
delete backFacePolyArray[i].pointlist;
}
delete frontFacePolyArray;
delete frontEdgePolyArray;
delete backFacePolyArray;
delete backEdgePolyArray;
}